/**
 * NetworkEntry.java
 *
 * @author Hagen Boehm
 */


package SSF.OS.OSPFv2;


import java.util.Vector;
import java.util.Enumeration;


// ======================== class SSF.OS.OSPFv2.NetworkEntry ======================== //
/**
 *  A routing table entry describing the set of shortest paths leading to a network
 *  destination. This includes the ID of the area in which the link state information
 *  of this entry was built. All other values of these entries are encoded in the OSPFv2 
 *  Routing Table structure.
 */
public class NetworkEntry {

  // ........................ member data .......................... //

  /** This field indicates the area whose link state information has led to the network
   *  entry's collection of paths. Only the best area is kept, therefore it is encoded as
   *  single field in an entry.
   */
  public int area;

  /** The type of path of the set of shortest paths to the destination network. The values
   *  of pathType are specified in class OSPF.
   */
  public byte pathType;

  /** The link state cost of the paths to the network. */
  public int cost;

  /** This field is valid only if pathType is of TYPE_2_EXTERNAL. Then it indicates the cost
   *  of path's external portion.
   */
  public int type2Cost;

  /** In case of path-type INTRA_AREA this field references the LSA that directly references
   *  the destination. The current version of OSPFv2 does not support broadcast, so the 
   *  destination may be only a stub network, and therefore the value is always a ROUTER_LSA.
   */
  public LSA lsOrigin;

  /** A Vector holding all equal-cost paths in form of ShortestPath objects.*/
  public Vector equalCostPaths;


  // ---------------------------- constructor NetworkEntry ----------------------------- //
  /**
   * Constructs a new NetworkEntry and set the fields to the given values.
   * @param area ID of area whose link state information has led to this entry.
   * @param pType The path type of the set of shortest paths.
   * @param c The cost of the shortest paths.
   * @param t2c External portion of path's cost.
   * @param lso The LSA describing the LS Origin (currently only Router-LSAs, but not used
   *            in any calculations).
   * @param paths A Vector holding ShortestPath objects which uniquely identifies the various 
   *              shortest paths.
   */
  public NetworkEntry(int area, byte pType, int c, int t2c, LSA lso, Vector paths) {
    this.area = area;
    pathType = pType;
    cost = c;
    if (pathType == OSPF.TYPE_2_EXTERNAL) type2Cost = t2c;
    else type2Cost = 0;
    if (pathType == OSPF.INTRA_AREA) lsOrigin = lso;
    equalCostPaths = paths;
  }

  // ------------------------------- NetworkEntry.set ---------------------------------- //
  /**
   * Modify the values of an existing network entry.
   * @param area ID of area whose link state information has led to this entry.
   * @param pType The path type of the set of shortest paths.
   * @param c The cost of the shortest paths.
   * @param t2c External portion of path's cost.
   * @param lso The LSA describing the LS Origin (currently only Router-LSAs, but not used
   *            in any calculations).
   * @param paths A Vector holding the ShortestPath objects which uniquely identify the 
   *              shortest paths belonging to this network destination.
   */
  //  public void set(int area, byte pType, int c, int t2c, LSA lso, Vector paths) {
//      this.area = area;
//      pathType = pType;
//      cost = c;
//      if (pathType == OSPF.TYPE_2_EXTERNAL) type2Cost = t2c;
//      if (pathType == OSPF.INTRA_AREA) lsOrigin = lso;
//      equalCostPaths = paths;
//    }

  // -------------------------- NetworkEntry.equalCost -------------------------- //
  /** Test whether the cost of this NetworkEntry is equal to the cost of netwEntry.
   *  @param netwEntry NetworkEntry whose cost is compared.
   *  @return boolean value indicating whether the two costs are equal or not.
   */
  public boolean equalCost(NetworkEntry netwEntry) {
    return (cost == netwEntry.cost);
  }

  // ---------------------- NetworkEntry.sameShortestPaths ----------------------- //
  /** Test whether the equal-cost paths, stored in this NetworkEntry are the same as
   *  the one stored in netwEntry.
   *  @param netwEntry NetworkEntry whose equalCostPaths Vector is compared.
   *  @return boolean value indicating whether the equalCostPaths Vectors of both
   *          NetworkEntries are identical or not.
   */
  public boolean sameShortestPaths(NetworkEntry netwEntry) {
    if (equalCostPaths.size() != netwEntry.equalCostPaths.size()) {
      return false;
    } else {
      ShortestPath sp1;
      ShortestPath sp2;
      for (Enumeration e1 = equalCostPaths.elements(); e1.hasMoreElements(); ) {
	sp1 = (ShortestPath)e1.nextElement();
        for (Enumeration e2 = netwEntry.equalCostPaths.elements(); e2.hasMoreElements(); ) {
	  sp2 = (ShortestPath)e2.nextElement();
          if (!sp1.equals(sp2)) {
            if (e2.hasMoreElements()) continue;
            else return false;
	  } else {
	    break;
          }
        }
      }
    }
    return true;
  }

  // ---------------------------- NetworkEntry.equals ------------------------------- //
  /** Compare this NetworkEntry with another one. Return true if they are equal else false.
   *  @param netEntObj NetworkEntry to compare.
   *  @return boolean value indicating whether the two entries are equal or not.
   */
  @Override
public boolean equals(Object netEntObj) {
    if (!(netEntObj instanceof NetworkEntry)) return false;
    NetworkEntry netwEntry = (NetworkEntry)netEntObj;
    if (pathType != netwEntry.pathType) return false;
    if (cost != netwEntry.cost) return false;
    if (equalCostPaths.size() != netwEntry.equalCostPaths.size()) {
      return false;
    } else {
      ShortestPath sp1;
      ShortestPath sp2;
      for (Enumeration e1 = equalCostPaths.elements(); e1.hasMoreElements(); ) {
	sp1 = (ShortestPath)e1.nextElement();
        for (Enumeration e2 = netwEntry.equalCostPaths.elements(); e2.hasMoreElements(); ) {
	  sp2 = (ShortestPath)e2.nextElement();
          if (!sp1.equals(sp2)) {
            if (e2.hasMoreElements()) continue;
            else return false;
	  } else {
	    break;
          }
        }
      }
    }
    return true;
  }

} // end of class NetworkEntry.
